package org.finesys.common.netty.websocket.support;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.*;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;

import java.net.SocketAddress;
import java.nio.ByteBuffer;

public class NettySession {

    private final Channel channel;

    public NettySession(Channel channel) {
        this.channel = channel;
    }

    /**
     * 设置子协议
     *
     * @param subprotocols 子协议
     */
    public void setSubprotocols(String subprotocols) {
        setAttribute("subprotocols", subprotocols);
    }

    /**
     * 获取缓存值
     */
    public <T> T getAttribute(String name) {
        AttributeKey<T> attributeKey = AttributeKey.valueOf(name);
        return channel.attr(attributeKey).get();
    }

    /**
     * 设置缓存值
     */
    public <T> void setAttribute(String name, T value) {
        AttributeKey<T> attributeKey = AttributeKey.valueOf(name);
        channel.attr(attributeKey).set(value);
    }

    /**
     * 从tail节点传播到header节点传播文本内容
     */
    public ChannelFuture sendText(String message) {
        return channel.writeAndFlush(new TextWebSocketFrame(message));
    }

    /**
     * 从tail节点传播到header节点传播文本内容
     */
    public ChannelFuture sendText(ByteBuf byteBuf) {
        return channel.writeAndFlush(new TextWebSocketFrame(byteBuf));
    }

    /**
     * 从tail节点传播到header节点传播文本内容
     */
    public ChannelFuture sendText(ByteBuffer byteBuffer) {
        ByteBuf byteBuf = channel.alloc().buffer(byteBuffer.remaining());
        byteBuf.writeBytes(byteBuffer);
        return channel.writeAndFlush(new TextWebSocketFrame(byteBuf));
    }

    /**
     * 从tail节点传播到header节点传播文本内容
     */
    public ChannelFuture sendText(TextWebSocketFrame textWebSocketFrame) {
        return channel.writeAndFlush(textWebSocketFrame);
    }

    /**
     * 从tail节点传播到header节点传播二进制流信息
     */
    public ChannelFuture sendBinary(byte[] bytes) {
        ByteBuf byteBuf = channel.alloc().buffer(bytes.length);
        return channel.writeAndFlush(new BinaryWebSocketFrame(byteBuf));
    }

    /**
     * 从tail节点传播到header节点传播二进制流信息
     */
    public ChannelFuture sendBinary(ByteBuf byteBuf) {
        return channel.writeAndFlush(new BinaryWebSocketFrame(byteBuf));
    }

    /**
     * 从tail节点传播到header节点传播二进制流信息
     */
    public ChannelFuture sendBinary(ByteBuffer byteBuffer) {
        ByteBuf byteBuf = channel.alloc().buffer(byteBuffer.remaining());
        byteBuf.writeBytes(byteBuffer);
        return channel.writeAndFlush(new BinaryWebSocketFrame(byteBuf));
    }

    /**
     * 从tail节点传播到header节点传播二进制流信息
     */
    public ChannelFuture sendBinary(BinaryWebSocketFrame binaryWebSocketFrame) {
        return channel.writeAndFlush(binaryWebSocketFrame);
    }

    public Channel getChannel() {
        return channel;
    }

    /**
     * 返回channel的全局唯一标识符 {@link Channel}.
     */
    public ChannelId id() {
        return channel.id();
    }

    /**
     * 返回此通道的配置
     */
    public ChannelConfig config() {
        return channel.config();
    }

    /**
     * 返回通道的打开状态，如果处于打开状态并且稍后可能处于活动状态，则返回true
     */
    public boolean isOpen() {
        return channel.isOpen();
    }

    /**
     * 通道是否已注册到EventLoop
     */
    public boolean isRegistered() {
        return channel.isRegistered();
    }

    /**
     * 是否处于活动状态并且已连接
     */
    public boolean isActive() {
        return channel.isActive();
    }

    /**
     * 返回通道实现的属性
     */
    public ChannelMetadata metadata() {
        return channel.metadata();
    }

    /**
     * 返回此通道绑定到的本地地址
     */
    public SocketAddress localAddress() {
        return channel.localAddress();
    }

    /**
     * 返回此通道连接到的远程地址
     */
    public SocketAddress remoteAddress() {
        return channel.remoteAddress();
    }

    /**
     * 此方法总是返回相同的未来实例。
     */
    public ChannelFuture closeFuture() {
        return channel.closeFuture();
    }

    /**
     * true:当且仅当I/O线程将执行请求的写入时立即操作。此方法返回时发出的任何写入请求
     * false:排队，直到I/O线程准备好处理排队写入请求。
     */
    public boolean isWritable() {
        return channel.isWritable();
    }

    /**
     * 获取在｛@link#isWritable（）｝返回之前可以写入的字节数｛@code false｝。此数量将始终为非负数。
     * 如果｛@link#isWritable（）｝是｛@code false｝，则为0。
     */
    public long bytesBeforeUnwritable() {
        return channel.bytesBeforeUnwritable();
    }

    /**
     * 获取必须从基础缓冲区中排出的字节数，直到｛@link#isWritable（）｝返回｛@code true｝。此数量将始终为非负数。
     * 如果｛@link#isWritable（）｝为｛@code true｝，则为0。
     */

    public long bytesBeforeWritable() {
        return channel.bytesBeforeWritable();
    }

    /**
     * 返回一个提供不安全操作的<em>仅内部使用</em>对象。
     */
    public Channel.Unsafe unsafe() {
        return channel.unsafe();
    }

    /**
     * 返回分配的PipeLine
     */
    public ChannelPipeline pipeline() {
        return channel.pipeline();
    }

    /**
     * 返回分配的｛@link ByteBufAllocator｝，它将用于分配｛@link ByteBuf｝s。
     */
    public ByteBufAllocator alloc() {
        return channel.alloc();
    }

    public Channel read() {
        return channel.read();
    }

    public Channel flush() {
        return channel.flush();
    }

    public ChannelFuture close() {
        return channel.close();
    }

    public ChannelFuture close(ChannelPromise promise) {
        return channel.close(promise);
    }
}
